#include "UdpClient.h"

void _die(char *mess) { perror(mess); exit(1); };

/*Constructor
 * initialize class parameter
 * */
UdpClient::UdpClient()
{

	this->port = 2000;
	this->received_byte = 0;
	this->received_packet = 0;
}

void UdpClient::setPort(int _port)
{
	this->port = _port;
}

bool UdpClient::startListening()
{

	this->keepRunning = true;

	/* Create the UDP socket */
    if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
      _die("Failed to create socket");
    }
    /* Construct the server sockaddr_in structure */
    memset(&sockaddr_server, 0, sizeof(sockaddr_server));       /* Clear struct */
    sockaddr_server.sin_family = AF_INET;                  /* Internet/IP */
    sockaddr_server.sin_addr.s_addr = htonl(INADDR_ANY);   /* Any IP address */
    sockaddr_server.sin_port = htons(this->port);			       /* server port */



    /* Bind the socket */
    serverlen = sizeof(sockaddr_server);
    if (bind(sock, (struct sockaddr *) &sockaddr_server, serverlen) < 0) {
      _die("Failed to bind server socket");
    }


	int iret1 = pthread_create( &thread1, NULL, (void* (*)(void *)) &UdpClient::startListeningThread,this);

}

/*keep listening on udp channel and call process for every datagramm
 * */
void UdpClient::startListeningThread(void *ptr )
{
//	printBold("Start Listening...");

	while (keepRunning) {
      /* Receive a message from the client */
      clientlen = sizeof(sockaddr_client);
      received = 0;



      if ((received = recvfrom(sock, buffer, BUFFSIZE, 0,
                               (struct sockaddr *) &sockaddr_client,
                               &clientlen)) < 0) {
        _die("Failed to receive message");
      }
      if (keepRunning == false)
      {
    	  continue;
      }
      //fprintf(stdout,"Client connected: %s, receivet byte: %i \n", inet_ntoa(sockaddr_client.sin_addr),received);

      gettimeofday(&l_time,NULL);


      received_byte += received;
      received_packet++;

      //initialize an UdpDatagram

	  UdpDatagram * udp_d = new UdpDatagram(buffer, received,(long)l_time.tv_usec,(struct sockaddr *)&sockaddr_client,(struct sockaddr *)&sockaddr_server);
      //call process

	  process(udp_d);


	  delete udp_d;

	}

//	printBold("Exit");

}


/*termina la connessione*/
 bool UdpClient::stopListening ()
 {
	 keepRunning = false;
	 shutdown(sock,SHUT_RD);
	 close(sock);
	 pthread_join(thread1,NULL);

	 return true;
 }
